package zzzhc.image.recognize.filter;

import java.util.ArrayList;

import zzzhc.image.recognize.ImageToken;
import zzzhc.image.recognize.RecognizeContext;
import zzzhc.image.recognize.SplitFilter;

public class BlockSplitFilter implements SplitFilter {

	private static final long serialVersionUID = -2176755905401376576L;

	private int threshold = 5;

	private ImageToken[] generate(RecognizeContext source) {
		int startX = -1;
		int endX = -1;
		int startY = -1;
		int endY = -1;
		ArrayList<ImageToken> result = new ArrayList<ImageToken>();
		int h = source.getHeight();
		int w = source.getWidth();
		while ((startX = nextX(source, endX+1)) != -1) {
			endX = endX(source, startX+1);
			if (endX == -1) {
				endX = w - 1;
			}
			startY = nextY(source, 0, startX, endX+1);
			endY = endY(source, startY, startX, endX+1);
			if (endY == -1) {
				endY = h - 1;
			}
			ImageToken token = source.split(startX, endX, startY, endY);
			if (token.getOneCount() > threshold) {
				result.add(token);
			} else {
				System.out.println("token's point less than " + threshold
						+ ",skipped");
			}
		}
		return result.toArray(new ImageToken[0]);
	}

	private int nextX(RecognizeContext source, int beginX) {
		int w = source.getWidth();
		for (int x = beginX; x < w; x++) {
			if (isYEmpty(source, x)) {
				continue;
			} else {
				return x;
			}
		}
		return -1;
	}

	private int endX(RecognizeContext source, int beginX) {
		int w = source.getWidth();
		for (int x = beginX; x < w; x++) {
			if (isYEmpty(source, x)) {
				return x;
			} else {
				continue;
			}
		}
		return -1;
	}

	private boolean isYEmpty(RecognizeContext source, int x) {
		int h = source.getHeight();
		for (int i = 0; i < h; i++) {
			if (source.getValue(x, i) != 0) {
				return false;
			}
		}
		return true;
	}

	private int nextY(RecognizeContext source, int startY, int startX, int endX) {
		int h = source.getHeight();
		for (int y = startY; y < h; y++) {
			if (isXEmpty(source, y, startX, endX)) {
				continue;
			} else {
				return y;
			}
		}
		return -1;
	}

	private int endY(RecognizeContext source, int startY, int startX, int endX) {
		int h = source.getHeight();
		for (int y = h - 1; y > startY; y--) {
			if (isXEmpty(source, y, startX, endX)) {
				continue;
			} else {
				return y + 1;
			}
		}
		return -1;
	}

	private boolean isXEmpty(RecognizeContext source, int y, int startX,
			int endX) {
		for (int x = startX; x < endX; x++) {
			if (source.getValue(x, y) != 0) {
				return false;
			}
		}
		return true;
	}

	public void doFilter(RecognizeContext context) {
		ImageToken[] tokens = generate(context);
		context.addTokens(tokens);
	}

	public int getThreshold() {
		return threshold;
	}

	public void setThreshold(int threshold) {
		this.threshold = threshold;
	}

}
